/*
Copyright 2010 Peter Krajnc, SCREENWORKER

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

  http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package com.screenworker.compactmvc.patterns
{
	import com.screenworker.compactmvc.core.CompactMVC;
	import com.screenworker.compactmvc.interfaces.IController;
	import com.screenworker.compactmvc.interfaces.IModel;
	import com.screenworker.compactmvc.vo.NoteVO;
	
	import flash.utils.setTimeout;
	
	/**
	 * <code>iController</code> implementation
	 * Controller Pattern class to be extended by subclasses
	 * 
	 * @author Peter Krajnc
	 * 
	 */	
	public class Controller implements IController
	{
		//VIEW NOTIFICATION TYPES
		public static const VIEW_REGISTER:String			= 'viewRegister';
		public static const VIEW_REMOVE:String				= 'viewRemove';
		public static const MODEL_REGISTER:String			= 'modelRegister';
		public static const MODEL_REMOVE:String				= 'modelRemove';
		public static const CONTROLLER_REGISTER:String		= 'controllerRegister';
		public static const CONTROLLER_REMOVE:String		= 'controllerRemove';
		public static const DEFAULT_NAME:String				= 'ApplicationController';
		
		private var _controllerName:String;
		private var _logLevel:String = CompactMVC.LOGLEVEL_NONE;
		private var _mainApplication:*;
		private var _logFunction:Function;
		/**
		 * Constructor 
		 * @param controllerName
		 * 
		 */		
		public function Controller(controllerName:String)
		{
			_controllerName = controllerName;	
			CompactMVC.getInstance().core.registerController(this);
		}
		
		/**
		 * Optional: Runs the notification after a specified delay (in milliseconds). 
		 * @param note
		 * @param delay (in milliseconds)
		 * 
		 */			
		public function sendNotification(note:NoteVO, delay:Number=0):void
		{
			if(delay && delay > 0)	
				setTimeout(	executeCommand, delay, note);
			else	
				executeCommand(note);
		}
		
		/**
		 * executes the command stateless and then removes the command
		 */  
		private function executeCommand(note:NoteVO):void
		{
			CompactMVC.getInstance().core.executeCommand(_controllerName, note);
		}
		
		/**
		 * notify one controller by Name
		 * @param controllerName
		 * @param notificationType
		 * @param data
		 * 
		 */		
		public function sendJunctionNotification(controllerName:String, notificationType:String, data:Object=null):void
		{
			CompactMVC.getInstance().core.retrieveController(controllerName).sendNotification( new NoteVO(notificationType, data) );
		}
		
      	/**
      	 * registers a Model 
      	 * @param modelName
      	 * @param modeClassRef
      	 * 
      	 */		
      	public function registerModel(modelName:String, modeClassRef:Class):void
      	{
      		CompactMVC.getInstance().core.registerModel(this, modelName, modeClassRef);
      	}
      	
      	/**
      	 * removes a Model 
      	 * @param modelName
      	 * 
      	 */      	
      	public function removeModel(modelName:String):void
      	{
      		CompactMVC.getInstance().core.removeModel(this, modelName);
      	}
      	
      	/**
      	 * retrieves a Model 
      	 * @param modelName
      	 * @return 
      	 * 
      	 */      	
      	public function retrieveModel(modelName:String):IModel
      	{
      		return CompactMVC.getInstance().core.retrieveModel(this, modelName);
      	}
      	
      	public function isModelRegistered(modelName:String):Boolean
      	{
      		return CompactMVC.getInstance().core.isModelRegistered(_controllerName, modelName);
      	}
      	
      	public function registerCommand(notificationType:String, commandClassRef:Class):void
      	{
      		CompactMVC.getInstance().core.registerCommand(this, notificationType, commandClassRef);
      	}
      	
      	public function removeCommand(notificationType:String):void
      	{
      		CompactMVC.getInstance().core.removeCommand(this, notificationType);
      	}
      	
      	public function retrieveCommand(notificationType:String):Class
      	{
      		return CompactMVC.getInstance().core.retrieveCommand(_controllerName, notificationType);
      	}
      	
      	/**
      	 * retrieves a registered View Instance
      	 * @param viewName
      	 * @return 
      	 * 
      	 */      	
      	public function retrieveView(viewName:String):Object
      	{
      		return CompactMVC.getInstance().core.retrieveView(_controllerName, viewName);
      	}
      	
      	public function isViewRegistered(viewName:String):Boolean
      	{
      		return CompactMVC.getInstance().core.isViewRegistered(_controllerName, viewName);
      	}
      	
      	public function retrieveAllRegisteredViews():Array
      	{
      		return CompactMVC.getInstance().core.retrieveAllRegisteredViews(_controllerName);
      		
      	}
      	
      	/**
      	 * removes the registered View 
      	 * @param viewName
      	 * 
      	 */      	
      	public function removeView(viewName:String):void
      	{ 	
      		//then remove registered view from list
      		CompactMVC.getInstance().core.removeView(_controllerName, viewName);
      	}
        
        
        /**
         * overriden by Subclasses
		 * a good place at startup to register commands and models used by the Application
         * @param note
         * 
         */        
        public function registerHandler():void {}
		
		
		/**
		 * resets the Controller
		 */		
		public function cleanup():void 
		{	
			_mainApplication = null;
			_logFunction = null;
			CompactMVC.getInstance().core.cleanup(_controllerName);	
		}
        
        /**
         * returns the controllname 
         * @return 
         * 
         */        
        public function getName():String
        {
        	return _controllerName;
        }
        
        /**
         * set here the logLevel to traceout needed infromation about the Framework
         * @param value Debugger.ALL, Debugger.NONE ...
         * 
         */        
        public function set logLevel(type:String):void
        {
        	_logLevel = type;
        }
        
        /**
         * returns the logLevel Type
         * @return 
         * 
         */        
        public function get logLevel():String
        {
        	return _logLevel;
        }
        
        /**
		 * set external log Method to pass LogMessages (overrides the internal used log Method)
		 * @param value
		 * 
		 */		
		public function set logFunction(value:Function):void
		{
			_logFunction = value;
		}
		
		/**
		 * returns the log Method
		 * @return 
		 * 
		 */		
		public function get logFunction():Function
		{
			return _logFunction;
		}
		
        /**
         * For FLEX, AIR use only!
         * Hold Reference to MainApplication e.g. to add NativeMenu, get Flash Variables, ...
         * @param value
         * 
         */        
        public function set mainApplication(value:*):void
        {
        	_mainApplication = value;
        	if(_mainApplication != null)
        	{
        		_mainApplication.addEventListener('preinitialize', flexEventHandler);
        		_mainApplication.addEventListener('creationComplete', flexEventHandler);
        		_mainApplication.addEventListener('applicationComplete', flexEventHandler);
        	}
        }
        
        /**
         * retrieves the mainApplication 
         * @return 
         * 
         */        
        public function get mainApplication():*
        {
        	return _mainApplication;
        }
        
        /**
         * handles the flexEvents to notify Commands and ViewManagers 
         * @param e
         * 
         */        
        private function flexEventHandler(e:*):void
        {   
        	sendNotification( new NoteVO(e.type) );     	
        }
        
      
	}
}
